﻿using System.Collections.Specialized;

namespace KinonekoSoftware.Foundation.UI.Controls.Panels
{
    /// <summary>
    ///     UnifiedColumnPanel
    /// </summary>
    /// <remarks>
    ///     当不需要Grid的行、列分隔等功能时建议用此轻量级类代替
    /// </remarks>
    public class UnifiedColumnPanel : Panel
    {
        
        private bool _skip;
        private bool _measure;

        protected override void OnRenderSizeChanged(SizeChangedInfo sizeInfo)
        {
            _skip    = false;
            _measure = false;
            
            base.OnRenderSizeChanged(sizeInfo);
        }

        protected override void OnChildDesiredSizeChanged(UIElement child)
        {
            if (_skip && _measure)
            {
                return;
            }

            base.OnChildDesiredSizeChanged(child);
        }
        
        
        protected override Size MeasureOverride(Size constraint)
        {
            var column = Column;
            var row   = (InternalChildren.Count + column - 1) / column;
            var w     = 0d;
            var h     = 0d;

            //
            // 第一次测量的时候，也就是这个Panel第一次初始化的时候
            // 会给一个长和宽都是无限大的Size
            // 尽量将所有的控件都布局在第一行
            if (double.IsInfinity(constraint.Width) && double.IsInfinity(constraint.Height))
            {
                foreach (UIElement element in InternalChildren)
                {
                    //
                    //
                    element.Measure(constraint);
                    element.Measure(new Size(element.DesiredSize.Width / column, constraint.Height));

                    w = Math.Max(w, element.DesiredSize.Width);
                    h = Math.Max(h, element.DesiredSize.Height);
                }

                return new Size(w * column, h * row);
            }

            w = constraint.Width / column;
            var size = new Size(w, constraint.Height);
            var h1   = 0d;
            
            for (var i = 0; i < InternalChildren.Count;)
            {
                h = 0;
                w = 0;
                
                for (var c = 0; c < column && i < InternalChildren.Count;)
                {
                    var item = InternalChildren[i];
                    item.Measure(size);
                    
                    //
                    //
                    h = Math.Max(h, item.DesiredSize.Height);
                    
                    c++;
                    i++;
                }
                
                //
                //
                h1 += h;
            }

            return new Size(w * column, h1);
        }

        protected override Size ArrangeOverride(Size finalSize)
        {
            var column = Column;    
            var w      = finalSize.Width / column;
            var top    = 0d;
            
            
            _measure = true;
            _skip    = true;

            for (var i = 0; i < InternalChildren.Count;)
            {
                var h = 0d;

                for (var n = 0; n < column && n + i < InternalChildren.Count; n++)
                {
                    h = Math.Max(h, InternalChildren[n + i].DesiredSize.Height);
                }

                for (var n = 0; n < column && i < InternalChildren.Count; )
                {
                    var x       = i % column;
                    var element = InternalChildren[i];
                    var rect    = new Rect(x * w, top, w, h);
                    element.Arrange(rect);
                    n++;
                    i++;
                }

                top += h;
            }
            return finalSize;
        }


        public static readonly DependencyProperty ColumnProperty = DependencyProperty.Register(
            nameof(Column),
            typeof(int),
            typeof(UnifiedColumnPanel),
            new FrameworkPropertyMetadata(2, FrameworkPropertyMetadataOptions.AffectsArrange | FrameworkPropertyMetadataOptions.AffectsMeasure));

        public int Column
        {
            get => (int)GetValue(ColumnProperty);
            set => SetValue(ColumnProperty, value);
        }
    }
}